package org.example.algorithm;

import com.google.common.collect.Range;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;

/**
 * @Title : DateRangeShardingAlgorithm
 * @Description: :
 * @author: libo@juzishuke.com
 * @date: 2023/11/15 15:22
 * @Version:1.0
 */
@Slf4j
public class DateRangeShardingAlgorithm implements RangeShardingAlgorithm<Date> {

    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames,
            RangeShardingValue<Date> rangeShardingValue) {
        List<String> list = new ArrayList<>();
        log.info("availableTargetNames : " + availableTargetNames);
        log.info(rangeShardingValue.toString());
        Range<Date> valueRange = rangeShardingValue.getValueRange();
        Date defaultLow = new Date(1698817571000L); // 2023-11-01
        Date defaultHigh = new Date(1735710371000L); // 2025-01-01
        Date lowerDate = valueRange.hasLowerBound() ? valueRange.lowerEndpoint() : defaultLow;
        Date upperDate = valueRange.hasUpperBound() ? valueRange.upperEndpoint() : defaultHigh;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
        Calendar splitDate = Calendar.getInstance();
        splitDate.set(2023, 10, 01, 00, 00, 00);
        //        String lowerSuffix = sdf.format(lowerDate);
        //        String upperSuffix = sdf.format(upperDate);
        Date date = lowerDate;
        Calendar cal = Calendar.getInstance();
        TreeSet<String> suffixList = new TreeSet<>();
        while (date.compareTo(upperDate) <= 0) {
            if (date.compareTo(splitDate.getTime()) <= 0) {
                suffixList.add(rangeShardingValue.getLogicTableName());
            } else {
                suffixList.add(rangeShardingValue.getLogicTableName().concat("_")
                        .concat(sdf.format(date)));
            }
            cal.setTime(date);
            cal.add(Calendar.MONTH, 1);
            date = cal.getTime();
        }
        if(date.getMonth() == upperDate.getMonth()){
            suffixList.add(rangeShardingValue.getLogicTableName().concat("_")
                    .concat(sdf.format(date)));
        }

        suffixList.retainAll(availableTargetNames);
        //        for (String tableName : availableTargetNames) {
        //            if (containTableName(suffixList, tableName)) {
        //                list.add(tableName);
        //            }
        //        }
        log.info("match tableNames-----------------------" + suffixList.toString());
        return suffixList;
    }

    private boolean containTableName(Set<String> suffixList, String tableName) {
        boolean flag = false;
        for (String s : suffixList) {
            if (tableName.endsWith(s)) {
                flag = true;
                break;
            }
        }
        return flag;
    }
}
